using System;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Storage;
using Microsoft.Extensions.Logging;
using JGSY.CMS.LowCode.Platform.Domain.Interfaces;
using JGSY.CMS.LowCode.Platform.Infrastructure.CmsDbContext;
using JGSY.CMS.LowCode.Platform.Infrastructure.Repositories;

namespace JGSY.CMS.LowCode.Platform.Infrastructure.UnitOfWork
{
    /// <summary>
    /// 工作单元实现
    /// 提供统一的事务管理和仓储访问，确保数据操作的一致性和完整性
    /// </summary>
    /// <remarks>
    /// 工作单元模式的实现，主要功能包括：
    /// - 统一的数据库事务管理
    /// - 仓储实例的延迟加载和缓存
    /// - 批量提交数据变更
    /// - 资源的自动释放和清理
    /// 
    /// 使用场景：
    /// - 需要跨多个仓储进行事务操作
    /// - 批量数据操作需要保证原子性
    /// - 复杂业务流程的数据一致性保证
    /// </remarks>
    public class UnitOfWork : IUnitOfWork
    {
        private readonly LowCodeDbContext _context;
        private readonly ILogger<UnitOfWork> _logger;
        private readonly ILoggerFactory _loggerFactory;
        private IDbContextTransaction? _transaction;
        private bool _disposed = false;

        // 仓储实例缓存
        private IArticleRepository? _articles;
        private ICategoryRepository? _categories;
        private IUserRepository? _users;
        private IRoleRepository? _roles;
        private IDepartmentRepository? _departments;
        private ITeamRepository? _teams;
        private ITeamMemberRepository? _teamMembers;
        private ITemplateRepository? _templates;
        private IProductRepository? _products;
        private IContentRepository? _contents;
        private IFormRepository? _forms;
        private IFieldRepository? _fields;
        private IFormSubmissionRepository? _formSubmissions;
        private IPageRepository? _pages;
        private IMediaFileRepository? _mediaFiles;
        private ISystemSettingRepository? _systemSettings;
        private IAuditLogRepository? _auditLogs;
        private ISecurityEventRepository? _securityEvents;
        private ILoginHistoryRepository? _loginHistories;
        private IUserDeviceRepository? _userDevices;
        private ITwoFactorRepository? _twoFactors;
        private IRiskAssessmentRepository? _riskAssessments;
        private IPublishRepository? _publishes;
        private IWorkflowRepository? _workflows;
        private IWorkflowInstanceRepository? _workflowInstances;
        private IWorkflowTaskRepository? _workflowTasks;
        private IPermissionRepository? _permissions;
        private IUserRoleRepository? _userRoles;

        /// <summary>
        /// 初始化工作单元实例
        /// </summary>
        /// <param name="context">数据库上下文</param>
        /// <param name="logger">日志记录器</param>
        /// <param name="loggerFactory">日志工厂</param>
        /// <exception cref="ArgumentNullException">当任何参数为null时抛出</exception>
        public UnitOfWork(LowCodeDbContext context, ILogger<UnitOfWork> logger, ILoggerFactory loggerFactory)
        {
            _context = context ?? throw new ArgumentNullException(nameof(context));
            _logger = logger ?? throw new ArgumentNullException(nameof(logger));
            _loggerFactory = loggerFactory ?? throw new ArgumentNullException(nameof(loggerFactory));
        }

        #region 仓储属性

        /// <summary>
        /// 文章仓储
        /// </summary>
        /// <remarks>
        /// 使用延迟加载模式，首次访问时创建实例并缓存
        /// </remarks>
        public IArticleRepository Articles =>
            _articles ??= new ArticleRepository(_context);

        /// <summary>
        /// 分类仓储
        /// </summary>
        /// <remarks>
        /// 使用延迟加载模式，首次访问时创建实例并缓存
        /// </remarks>
        public ICategoryRepository Categories =>
            _categories ??= new CategoryRepository(_context);

        /// <summary>
        /// 用户仓储
        /// </summary>
        /// <remarks>
        /// 使用延迟加载模式，首次访问时创建实例并缓存
        /// </remarks>
        public IUserRepository Users =>
            _users ??= new UserRepository(_context);

        /// <summary>
        /// 角色仓储
        /// </summary>
        /// <remarks>
        /// 使用延迟加载模式，首次访问时创建实例并缓存
        /// </remarks>
        public IRoleRepository Roles =>
            _roles ??= new RoleRepository(_context);

        /// <summary>
        /// 部门仓储
        /// </summary>
        /// <remarks>
        /// 使用延迟加载模式，首次访问时创建实例并缓存
        /// </remarks>
        public IDepartmentRepository Departments =>
            _departments ??= new DepartmentRepository(_context, _loggerFactory.CreateLogger<DepartmentRepository>());

        /// <summary>
        /// 团队仓储
        /// </summary>
        /// <remarks>
        /// 使用延迟加载模式，首次访问时创建实例并缓存
        /// </remarks>
        public ITeamRepository Teams =>
            _teams ??= new TeamRepository(_context);

        /// <summary>
        /// 团队成员仓储
        /// </summary>
        /// <remarks>
        /// 使用延迟加载模式，首次访问时创建实例并缓存
        /// </remarks>
        public ITeamMemberRepository TeamMembers =>
            _teamMembers ??= new TeamMemberRepository(_context);

        /// <summary>
        /// 模板仓储
        /// </summary>
        /// <remarks>
        /// 使用延迟加载模式，首次访问时创建实例并缓存
        /// </remarks>
        public ITemplateRepository Templates =>
            _templates ??= new TemplateRepository(_context);

        /// <summary>
        /// 产品仓储
        /// </summary>
        /// <remarks>
        /// 使用延迟加载模式，首次访问时创建实例并缓存
        /// </remarks>
        public IProductRepository Products =>
            _products ??= new ProductRepository(_context);

        public IContentRepository Contents =>
            _contents ??= new ContentRepository(_context);

        public IFormRepository Forms =>
            _forms ??= new FormRepository(_context);

        public IFieldRepository Fields =>
            _fields ??= new FieldRepository(_context);

        public IFormSubmissionRepository FormSubmissions =>
            _formSubmissions ??= new FormSubmissionRepository(_context);

        public IPageRepository Pages =>
            _pages ??= new PageRepository(_context);

        public IMediaFileRepository MediaFiles =>
            _mediaFiles ??= new MediaFileRepository(_context);

        public ISystemSettingRepository SystemSettings =>
            _systemSettings ??= new SystemSettingRepository(_context);

        public IAuditLogRepository AuditLogs =>
            _auditLogs ??= new AuditLogRepository(_context);

        public ISecurityEventRepository SecurityEvents =>
            _securityEvents ??= new SecurityEventRepository(_context);

        public ILoginHistoryRepository LoginHistories =>
            _loginHistories ??= new LoginHistoryRepository(_context);

        public IUserDeviceRepository UserDevices =>
            _userDevices ??= new UserDeviceRepository(_context);

        public ITwoFactorRepository TwoFactors =>
            _twoFactors ??= new TwoFactorRepository(_context);

        public IRiskAssessmentRepository RiskAssessments =>
            _riskAssessments ??= new RiskAssessmentRepository(_context);

        public IPublishRepository Publishes =>
            _publishes ??= new PublishRepository(_context);

        public IWorkflowRepository Workflows =>
            _workflows ??= new WorkflowRepository(_context);

        public IWorkflowInstanceRepository WorkflowInstances =>
            _workflowInstances ??= new WorkflowInstanceRepository(_context);

        public IWorkflowTaskRepository WorkflowTasks =>
            _workflowTasks ??= new WorkflowTaskRepository(_context);

        public IPermissionRepository Permissions =>
            _permissions ??= new PermissionRepository(_context);

        public IUserRoleRepository UserRoles =>
            _userRoles ??= new UserRoleRepository(_context);

        #endregion

        #region 事务管理

        /// <summary>
        /// 开始数据库事务
        /// 创建新的数据库事务用于保证多个操作的原子性
        /// </summary>
        /// <returns>事务开始操作的异步任务</returns>
        /// <exception cref="Exception">数据库事务创建失败时抛出</exception>
        /// <remarks>
        /// 如果已存在活动事务，会先释放旧事务再创建新事务。
        /// 事务开始后，所有通过此工作单元进行的数据变更都将在同一事务中执行。
        /// </remarks>
        public async Task BeginTransactionAsync()
        {
            try
            {
                if (_transaction != null)
                {
                    _logger.LogWarning("Transaction already exists, disposing existing transaction");
                    await _transaction.DisposeAsync();
                }

                _transaction = await _context.Database.BeginTransactionAsync();
                _logger.LogInformation("Transaction started");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Failed to start transaction");
                throw;
            }
        }

        /// <summary>
        /// 提交数据库事务
        /// 将事务中的所有数据变更永久保存到数据库
        /// </summary>
        /// <returns>事务提交操作的异步任务</returns>
        /// <exception cref="InvalidOperationException">当前没有活动事务时抛出</exception>
        /// <exception cref="Exception">事务提交过程中发生错误时抛出</exception>
        /// <remarks>
        /// 提交成功后，事务中的所有数据变更将变为永久性。
        /// 提交失败时，事务会自动回滚，所有变更都将丢失。
        /// </remarks>
        public async Task CommitTransactionAsync()
        {
            try
            {
                if (_transaction == null)
                {
                    _logger.LogWarning("No transaction to commit");
                    return;
                }

                await _context.SaveChangesAsync();
                await _transaction.CommitAsync();
                _logger.LogInformation("Transaction committed successfully");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Failed to commit transaction");
                await RollbackTransactionAsync();
                throw;
            }
            finally
            {
                if (_transaction != null)
                {
                    await _transaction.DisposeAsync();
                    _transaction = null;
                }
            }
        }

        /// <summary>
        /// 回滚数据库事务
        /// </summary>
        /// <returns>异步任务</returns>
        /// <remarks>
        /// <para>功能说明：</para>
        /// <list type="bullet">
        /// <item><description>安全回滚当前活动事务</description></item>
        /// <item><description>自动清理事务资源</description></item>
        /// <item><description>记录回滚操作日志</description></item>
        /// </list>
        /// 
        /// <para>异常处理：</para>
        /// <list type="bullet">
        /// <item><description>无事务时记录警告日志</description></item>
        /// <item><description>回滚失败时记录错误并重新抛出异常</description></item>
        /// <item><description>确保事务资源始终被正确释放</description></item>
        /// </list>
        /// 
        /// <para>使用场景：</para>
        /// <list type="bullet">
        /// <item><description>业务逻辑执行失败时回滚更改</description></item>
        /// <item><description>异常发生时恢复数据一致性</description></item>
        /// <item><description>手动控制事务回滚时机</description></item>
        /// </list>
        /// </remarks>
        /// <exception cref="InvalidOperationException">事务回滚操作失败时抛出</exception>
        public async Task RollbackTransactionAsync()
        {
            try
            {
                if (_transaction == null)
                {
                    _logger.LogWarning("No transaction to rollback");
                    return;
                }

                await _transaction.RollbackAsync();
                _logger.LogInformation("Transaction rolled back");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Failed to rollback transaction");
                throw;
            }
            finally
            {
                if (_transaction != null)
                {
                    await _transaction.DisposeAsync();
                    _transaction = null;
                }
            }
        }

        /// <summary>
        /// 异步保存所有实体更改到数据库
        /// </summary>
        /// <returns>受影响的实体数量</returns>
        /// <remarks>
        /// <para>功能说明：</para>
        /// <list type="bullet">
        /// <item><description>将内存中的所有更改持久化到数据库</description></item>
        /// <item><description>返回实际受影响的记录数量</description></item>
        /// <item><description>记录操作详情和性能指标</description></item>
        /// </list>
        /// 
        /// <para>性能特性：</para>
        /// <list type="bullet">
        /// <item><description>批量提交所有更改以提高效率</description></item>
        /// <item><description>自动检测和优化SQL语句</description></item>
        /// <item><description>支持大批量数据操作</description></item>
        /// </list>
        /// 
        /// <para>使用场景：</para>
        /// <list type="bullet">
        /// <item><description>完成业务操作后持久化数据</description></item>
        /// <item><description>事务提交前的最终保存</description></item>
        /// <item><description>批量操作的统一保存点</description></item>
        /// </list>
        /// </remarks>
        /// <exception cref="DbUpdateException">数据库更新操作失败时抛出</exception>
        /// <exception cref="DbUpdateConcurrencyException">并发冲突时抛出</exception>
        public async Task<int> SaveChangesAsync()
        {
            try
            {
                var result = await _context.SaveChangesAsync();
                _logger.LogDebug("Saved {ChangeCount} changes to database", result);
                return result;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Failed to save changes to database");
                throw;
            }
        }

        #endregion

        #region 保存点管理

        /// <summary>
        /// 创建数据库事务保存点
        /// </summary>
        /// <param name="name">保存点名称，用于标识和回滚操作</param>
        /// <returns>异步任务</returns>
        /// <remarks>
        /// <para>功能说明：</para>
        /// <list type="bullet">
        /// <item><description>在现有事务中创建命名保存点</description></item>
        /// <item><description>允许部分回滚而不影响整个事务</description></item>
        /// <item><description>支持嵌套事务和复杂业务流程</description></item>
        /// </list>
        /// 
        /// <para>保存点特性：</para>
        /// <list type="bullet">
        /// <item><description>保存点名称必须在事务中唯一</description></item>
        /// <item><description>可创建多个保存点形成层次结构</description></item>
        /// <item><description>保存点生命周期绑定到父事务</description></item>
        /// </list>
        /// 
        /// <para>使用场景：</para>
        /// <list type="bullet">
        /// <item><description>复杂业务流程的阶段性提交</description></item>
        /// <item><description>批量操作中的错误恢复点</description></item>
        /// <item><description>嵌套业务逻辑的独立控制</description></item>
        /// </list>
        /// </remarks>
        /// <exception cref="ArgumentException">保存点名称无效或已存在时抛出</exception>
        /// <exception cref="InvalidOperationException">无活动事务时抛出</exception>
        public async Task CreateSavepointAsync(string name)
        {
            try
            {
                if (_transaction == null)
                {
                    await BeginTransactionAsync();
                }

                await _transaction!.CreateSavepointAsync(name);
                _logger.LogDebug("Savepoint '{SavepointName}' created", name);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Failed to create savepoint '{SavepointName}'", name);
                throw;
            }
        }

        /// <summary>
        /// 回滚到指定的事务保存点
        /// </summary>
        /// <param name="name">目标保存点的名称</param>
        /// <returns>异步任务</returns>
        /// <remarks>
        /// <para>功能说明：</para>
        /// <list type="bullet">
        /// <item><description>将事务状态回滚到指定保存点</description></item>
        /// <item><description>撤销保存点之后的所有数据更改</description></item>
        /// <item><description>保留保存点之前的事务状态</description></item>
        /// </list>
        /// 
        /// <para>回滚特性：</para>
        /// <list type="bullet">
        /// <item><description>部分回滚，不影响整个事务</description></item>
        /// <item><description>自动清理后续保存点</description></item>
        /// <item><description>保持事务的活动状态</description></item>
        /// </list>
        /// 
        /// <para>使用场景：</para>
        /// <list type="bullet">
        /// <item><description>业务逻辑执行失败时的精确回滚</description></item>
        /// <item><description>批量操作中的错误恢复</description></item>
        /// <item><description>复杂流程的阶段性撤销</description></item>
        /// </list>
        /// </remarks>
        /// <exception cref="ArgumentException">保存点不存在时抛出</exception>
        /// <exception cref="InvalidOperationException">无活动事务时抛出</exception>
        public async Task RollbackToSavepointAsync(string name)
        {
            try
            {
                if (_transaction == null)
                {
                    _logger.LogWarning("No transaction available for savepoint rollback");
                    return;
                }

                await _transaction.RollbackToSavepointAsync(name);
                _logger.LogDebug("Rolled back to savepoint '{SavepointName}'", name);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Failed to rollback to savepoint '{SavepointName}'", name);
                throw;
            }
        }

        /// <summary>
        /// 释放指定的事务保存点
        /// </summary>
        /// <param name="name">要释放的保存点名称</param>
        /// <returns>异步任务</returns>
        /// <remarks>
        /// <para>功能说明：</para>
        /// <list type="bullet">
        /// <item><description>释放不再需要的保存点资源</description></item>
        /// <item><description>确认保存点之前的更改有效</description></item>
        /// <item><description>优化事务内存使用</description></item>
        /// </list>
        /// 
        /// <para>释放特性：</para>
        /// <list type="bullet">
        /// <item><description>释放后无法再回滚到该保存点</description></item>
        /// <item><description>自动提升保存点状态到事务级别</description></item>
        /// <item><description>减少事务管理开销</description></item>
        /// </list>
        /// 
        /// <para>使用场景：</para>
        /// <list type="bullet">
        /// <item><description>确认业务阶段成功完成</description></item>
        /// <item><description>清理不再需要的回滚点</description></item>
        /// <item><description>优化长事务的资源使用</description></item>
        /// </list>
        /// </remarks>
        /// <exception cref="ArgumentException">保存点不存在时抛出</exception>
        /// <exception cref="InvalidOperationException">无活动事务时抛出</exception>
        public async Task ReleaseSavepointAsync(string name)
        {
            try
            {
                if (_transaction == null)
                {
                    _logger.LogWarning("No transaction available for savepoint release");
                    return;
                }

                await _transaction.ReleaseSavepointAsync(name);
                _logger.LogDebug("Savepoint '{SavepointName}' released", name);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Failed to release savepoint '{SavepointName}'", name);
                throw;
            }
        }

        #endregion

        #region IDisposable

        /// <summary>
        /// 释放资源
        /// </summary>
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        /// <summary>
        /// 释放资源
        /// </summary>
        protected virtual void Dispose(bool disposing)
        {
            if (!_disposed && disposing)
            {
                try
                {
                    if (_transaction != null)
                    {
                        _transaction.Dispose();
                        _transaction = null;
                    }

                    _context?.Dispose();
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex, "Error occurred while disposing UnitOfWork");
                }
                finally
                {
                    _disposed = true;
                }
            }
        }

        /// <summary>
        /// 析构函数
        /// </summary>
        ~UnitOfWork()
        {
            Dispose(false);
        }

        #endregion
    }
}
